home *** CD-ROM | disk | FTP | other *** search
/ PC go! 2017 October / PCgo 10-2017 CD-ROM Germany.iso / nw.pak / Unnamed File 000144.txt < prev    next >
Encoding:
Text File  |  2015-07-29  |  7.5 KB  |  242 lines

  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4.  
  5. /**
  6.  * @fileoverview This implements a splitter element which can be used to resize
  7.  * elements in split panes.
  8.  *
  9.  * The parent of the splitter should be an hbox (display: -webkit-box) with at
  10.  * least one previous element sibling. The splitter controls the width of the
  11.  * element before it.
  12.  *
  13.  * <div class=split-pane>
  14.  *   <div class=left>...</div>
  15.  *   <div class=splitter></div>
  16.  *   ...
  17.  * </div>
  18.  *
  19.  */
  20.  
  21. cr.define('cr.ui', function() {
  22.   // TODO(arv): Currently this only supports horizontal layout.
  23.   // TODO(arv): This ignores min-width and max-width of the elements to the
  24.   // right of the splitter.
  25.  
  26.   /**
  27.    * Returns the computed style width of an element.
  28.    * @param {!Element} el The element to get the width of.
  29.    * @return {number} The width in pixels.
  30.    */
  31.   function getComputedWidth(el) {
  32.     return parseFloat(el.ownerDocument.defaultView.getComputedStyle(el).width) /
  33.         getZoomFactor(el.ownerDocument);
  34.   }
  35.  
  36.   /**
  37.    * This uses a WebKit bug to work around the same bug. getComputedStyle does
  38.    * not take the page zoom into account so it returns the physical pixels
  39.    * instead of the logical pixel size.
  40.    * @param {!Document} doc The document to get the page zoom factor for.
  41.    * @return {number} The zoom factor of the document.
  42.    */
  43.   function getZoomFactor(doc) {
  44.     var dummyElement = doc.createElement('div');
  45.     dummyElement.style.cssText =
  46.     'position:absolute;width:100px;height:100px;top:-1000px;overflow:hidden';
  47.     doc.body.appendChild(dummyElement);
  48.     var cs = doc.defaultView.getComputedStyle(dummyElement);
  49.     var rect = dummyElement.getBoundingClientRect();
  50.     var zoomFactor = parseFloat(cs.width) / 100;
  51.     doc.body.removeChild(dummyElement);
  52.     return zoomFactor;
  53.   }
  54.  
  55.   /**
  56.    * Creates a new splitter element.
  57.    * @param {Object=} opt_propertyBag Optional properties.
  58.    * @constructor
  59.    * @extends {HTMLDivElement}
  60.    */
  61.   var Splitter = cr.ui.define('div');
  62.  
  63.   Splitter.prototype = {
  64.     __proto__: HTMLDivElement.prototype,
  65.  
  66.     /**
  67.      * Initializes the element.
  68.      */
  69.     decorate: function() {
  70.       this.addEventListener('mousedown', this.handleMouseDown_.bind(this),
  71.                             true);
  72.       this.addEventListener('touchstart', this.handleTouchStart_.bind(this),
  73.                             true);
  74.     },
  75.  
  76.     /**
  77.      * Starts the dragging of the splitter. Adds listeners for mouse or touch
  78.      * events and calls splitter drag start handler.
  79.      * @param {number} clientX X position of the mouse or touch event that
  80.      *                         started the drag.
  81.      * @param {boolean} isTouchEvent True if the drag started by touch event.
  82.      */
  83.     startDrag: function(clientX, isTouchEvent) {
  84.       if (this.handlers_) {
  85.         console.log('Concurent drags');
  86.         this.endDrag_();
  87.       }
  88.       if (isTouchEvent) {
  89.         var endDragBound = this.endDrag_.bind(this);
  90.         this.handlers_ = {
  91.           'touchmove': this.handleTouchMove_.bind(this),
  92.           'touchend': endDragBound,
  93.           'touchcancel': endDragBound,
  94.  
  95.           // Another touch start (we somehow missed touchend or touchcancel).
  96.           'touchstart': endDragBound,
  97.         };
  98.       } else {
  99.         this.handlers_ = {
  100.           'mousemove': this.handleMouseMove_.bind(this),
  101.           'mouseup': this.handleMouseUp_.bind(this),
  102.         };
  103.       }
  104.  
  105.       var doc = this.ownerDocument;
  106.  
  107.       // Use capturing events on the document to get events when the mouse
  108.       // leaves the document.
  109.       for (var eventType in this.handlers_) {
  110.         doc.addEventListener(eventType, this.handlers_[eventType], true);
  111.       }
  112.  
  113.       this.startX_ = clientX;
  114.       this.handleSplitterDragStart();
  115.     },
  116.  
  117.     /**
  118.      * Ends the dragging of the splitter. Removes listeners set in startDrag
  119.      * and calls splitter drag end handler.
  120.      * @private
  121.      */
  122.     endDrag_: function() {
  123.       var doc = this.ownerDocument;
  124.       for (var eventType in this.handlers_) {
  125.         doc.removeEventListener(eventType, this.handlers_[eventType], true);
  126.       }
  127.       this.handlers_ = null;
  128.       this.handleSplitterDragEnd();
  129.     },
  130.  
  131.     /**
  132.      * Handles the mousedown event which starts the dragging of the splitter.
  133.      * @param {!Event} e The mouse event.
  134.      * @private
  135.      */
  136.     handleMouseDown_: function(e) {
  137.       e = /** @type {!MouseEvent} */(e);
  138.       this.startDrag(e.clientX, false);
  139.       // Default action is to start selection and to move focus.
  140.       e.preventDefault();
  141.     },
  142.  
  143.     /**
  144.      * Handles the touchstart event which starts the dragging of the splitter.
  145.      * @param {!Event} e The touch event.
  146.      * @private
  147.      */
  148.     handleTouchStart_: function(e) {
  149.       e = /** @type {!TouchEvent} */(e);
  150.       if (e.touches.length == 1) {
  151.         this.startDrag(e.touches[0].clientX, true);
  152.         e.preventDefault();
  153.       }
  154.     },
  155.  
  156.     /**
  157.      * Handles the mousemove event which moves the splitter as the user moves
  158.      * the mouse.
  159.      * @param {!MouseEvent} e The mouse event.
  160.      * @private
  161.      */
  162.     handleMouseMove_: function(e) {
  163.       this.handleMove_(e.clientX);
  164.     },
  165.  
  166.     /**
  167.      * Handles the touch move event.
  168.      * @param {!TouchEvent} e The touch event.
  169.      */
  170.     handleTouchMove_: function(e) {
  171.       if (e.touches.length == 1)
  172.         this.handleMove_(e.touches[0].clientX);
  173.     },
  174.  
  175.     /**
  176.      * Common part of handling mousemove and touchmove. Calls splitter drag
  177.      * move handler.
  178.      * @param {number} clientX X position of the mouse or touch event.
  179.      * @private
  180.      */
  181.     handleMove_: function(clientX) {
  182.       var rtl = this.ownerDocument.defaultView.getComputedStyle(this).
  183.           direction == 'rtl';
  184.       var dirMultiplier = rtl ? -1 : 1;
  185.       var deltaX = dirMultiplier * (clientX - this.startX_);
  186.       this.handleSplitterDragMove(deltaX);
  187.     },
  188.  
  189.     /**
  190.      * Handles the mouse up event which ends the dragging of the splitter.
  191.      * @param {!MouseEvent} e The mouse event.
  192.      * @private
  193.      */
  194.     handleMouseUp_: function(e) {
  195.       this.endDrag_();
  196.     },
  197.  
  198.     /**
  199.      * Handles start of the splitter dragging. Saves current width of the
  200.      * element being resized.
  201.      * @protected
  202.      */
  203.     handleSplitterDragStart: function() {
  204.       // Use the computed width style as the base so that we can ignore what
  205.       // box sizing the element has.
  206.       var leftComponent = this.previousElementSibling;
  207.       var doc = leftComponent.ownerDocument;
  208.       this.startWidth_ = parseFloat(
  209.           doc.defaultView.getComputedStyle(leftComponent).width);
  210.     },
  211.  
  212.     /**
  213.      * Handles splitter moves. Updates width of the element being resized.
  214.      * @param {number} deltaX The change of splitter horizontal position.
  215.      * @protected
  216.      */
  217.     handleSplitterDragMove: function(deltaX) {
  218.       var leftComponent = this.previousElementSibling;
  219.       leftComponent.style.width = this.startWidth_ + deltaX + 'px';
  220.     },
  221.  
  222.     /**
  223.      * Handles end of the splitter dragging. This fires a 'resize' event if the
  224.      * size changed.
  225.      * @protected
  226.      */
  227.     handleSplitterDragEnd: function() {
  228.       // Check if the size changed.
  229.       var leftComponent = this.previousElementSibling;
  230.       var doc = leftComponent.ownerDocument;
  231.       var computedWidth = parseFloat(
  232.           doc.defaultView.getComputedStyle(leftComponent).width);
  233.       if (this.startWidth_ != computedWidth)
  234.         cr.dispatchSimpleEvent(this, 'resize');
  235.     },
  236.   };
  237.  
  238.   return {
  239.     Splitter: Splitter
  240.   };
  241. });
  242.